﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace AcceptServer
{
    public class TQueue<T>
    {
        /// <summary>
        /// The private q which holds the actual data
        /// </summary>
        private readonly Queue<T> m_Queue;

        /// <summary>
        /// Lock for the Q
        /// </summary>
        private readonly ReaderWriterLockSlim LockQ = new ReaderWriterLockSlim();

        public int Count
        {
            get { return m_Queue.Count; }
        }



        /// <summary>
        /// Initializes the Queue
        /// </summary>
        public TQueue()
        {
            m_Queue = new Queue<T>();
        }

        /// <summary>
        /// Initializes the Queue
        /// </summary>
        /// <param name="capacity">the initial number of elements the queue can contain</param>
        public TQueue(int capacity)
        {
            m_Queue = new Queue<T>(capacity);
        }

        /// <summary>
        /// Initializes the Queue
        /// </summary>
        /// <param name="collection">the collection whose members are copied to the Queue</param>
        public TQueue(IEnumerable<T> collection)
        {
            m_Queue = new Queue<T>(collection);
        }


        /// <summary>
        /// Returns an enumerator that enumerates through the collection
        /// </summary>
        public IEnumerator<T> GetEnumerator()
        {
            Queue<T> localQ;

            // init enumerator
            LockQ.EnterReadLock();
            try
            {
                // create a copy of m_TList
                localQ = new Queue<T>(m_Queue);
            }
            finally
            {
                LockQ.ExitReadLock();
            }

            // get the enumerator
            foreach (T item in localQ)
                yield return item;
        }

        /// <summary>
        /// Adds an item to the queue
        /// </summary>
        /// <param name="item">the item to add to the queue</param>
        public void Enqueue(T item)
        {
            LockQ.EnterWriteLock();
            try
            {
                m_Queue.Enqueue(item);
            }

            finally
            {
                LockQ.ExitWriteLock();
            }
        }
        /// <summary>
        /// Removes and returns the item in the beginning of the queue
        /// </summary>
        public T Dequeue()
        {
            LockQ.EnterWriteLock();
            try
            {
                return m_Queue.Dequeue();
            }

            finally
            {
                LockQ.ExitWriteLock();
            }
        }

        /// <summary>
        /// Enqueues the list of items
        /// </summary>
        /// <param name="ItemsToQueue">list of items to enqueue</param>
        public void EnqueueAll(IEnumerable<T> ItemsToQueue)
        {
            LockQ.EnterWriteLock();
            try
            {
                // loop through and add each item
                foreach (T item in ItemsToQueue)
                    m_Queue.Enqueue(item);
            }

            finally
            {
                LockQ.ExitWriteLock();
            }
        }

        ///// <summary>
        ///// Enqueues the list of items
        ///// </summary>
        ///// <param name="ItemsToQueue">list of items to enqueue</param>
        //public void EnqueueAll(TList<T> ItemsToQueue)
        //{
        //    LockQ.EnterWriteLock();
        //    try
        //    {
        //        // loop through and add each item
        //        foreach (T item in ItemsToQueue)
        //            m_Queue.Enqueue(item);
        //    }

        //    finally
        //    {
        //        LockQ.ExitWriteLock();
        //    }
        //}

        ///// <summary>
        ///// Dequeues all the items and returns them as a thread safe list
        ///// </summary>
        //public TList<T> DequeueAll()
        //{
        //    LockQ.EnterWriteLock();
        //    try
        //    {
        //        // create return object
        //        TList<T> returnList = new TList<T>();

        //        // dequeue until everything is out
        //        while (m_Queue.Count > 0)
        //            returnList.Add(m_Queue.Dequeue());

        //        // return the list
        //        return returnList;
        //    }

        //    finally
        //    {
        //        LockQ.ExitWriteLock();
        //    }
        //}
    }
}
